package com.botann.projects.utils;

/**
 * stock
 * RSAEncrypt
 * Created by 刘山国 on 2019/4/19.
 * Copyright (c) 2017 伯坦科技. All rights reserved
 */

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSAEncrypt {


    public enum RSAKeyType {
        PUBLIC,
        PRIVATE;
    }

    public static String kPublic_Key_File = "/rsa_public_key.keystore";
    public static String kPrivate_Key_File = "/rsa_private_key.keystore";

    private static final String kPrivate_Key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCprh2hY6ZG8Zl2b+rF8G1o0NQVNsrTAIeQ6juxC92YS3xNYupEj3VnWF7J44dYhmToV195Fo5BWYkvVkCR+TMZ1r730HrwWTh9eMfbG9Y7sr5XkPtpZ9Mmitd0tpEyaygNrx8MINzajPj41DbeiLEfnrDfLvnLLjg/IBMUteidKV9HTBgg6tzePMs3niG9TEZ9YWWBusKjGWYUHkcBfVsUYKF04TzNJZ5/xmtPfAbubgJFKRinHJmb8Bp+Ifkd1BVqtlAVxU4ZVc/dK0F+iccFSxqOQi+byProi6otdiFLB9Fj8P7J1x4mazvayOJRpu5X5YKCzQuS4i4DQe5yAnVzAgMBAAECggEANTCfmTfjp9mUgcwTjHkR0wmjcgL7EanY1VSX4agWjuca0CdxyIwwAXVyQVdR1i5K84pwI0Uu0s1+c5hWJWw42KC4vHZeE3nke3ChNc5EGfKuOET6itBBIJPldnDEk0mEBMYgtWyXzuriIR5lFN1EqOTWDSBsrYSPnTowwQ1FHf6XdFCq9W2YdlmlEbUiU+3y/3SFM37d1W+ciROxcZhYF1QTvpQkFsCkst0pnmPVTTxUxcW2nH+cYKZ1akrSBmOpTkk8CfZpIZOlLc++iviQwyMLyfWCs3KHTDrzVegMLim+ijI8vJM5yK+uavrmL+KMqH4ipKfEKb4U3tx3kTS0AQKBgQDQ4qeGZAA28jL1Bw9/xxuSZJUuSeUgcY+d+eIaHOt77cEfAW50bTUf8hAxmmYtbyg5ThqH8YKIpcyYjS/KkyxDn1JJdyOxUZ4FE6Q749clzWFEL3lr7BcKnbzSsN5KJe/GMp05NFnhBoUC/eLdO99cJujw1BY9b9wsdVHQIvSnCQKBgQDP87G8ujfVUxcNeZnyZaN1U1IjlEty4zcEAbV2/sP+dQamGzm6SFqenAs0LiOPg9aB9e3pmpvAAt0NS9vlwQO8b9hVVW3vbAtyPuYrjUA9lV+uu0dpDruS/9BxMhVsAIi7l5kRj7UvOBr37rnxaWi18Q0tj3tH7/R6ajuaJqB7mwKBgQC3hVsgBL33iGVix7hDUECWJs62o2+uSHegmQmgXaY69JFG13Ae1E/naDn4CqoY4t9ZMZi3tWU0/044/VpuxU0PgGvAZe8y+/00gqQ5hhzhdocta/Rm8D7yMdHS3lf+l0QJQzDFMIyC2sKD9WGbc93yzbC83elIQv4TBWRC1GNUWQKBgQCkX5F/h4a4pawUJ6mLU9HH3KuRmhelYXrMPPmObMTJrwEpbV3NJIIU221zuoC7YU++fIGpZF92gAzxBKR10IK+gX3zvcpfNP07OgLALC+6Pgda24gPv+h+wpylzRvnuehat/LzUa+6+lM+5UGvVE3Dex2ahM7CxyZtWOlx6NRzvwKBgChyHhXHOIi8cVPIjAzafuOp6sgr9vjNrkeSVC/AU7Vq4FY+o9Y1+OBXxHKiwltQYYA1X0SNtSoMtUU0e4T0BZnFQY9Lr77coxkqVWtucf0ynhM35avDMa8yoh/7AzGkTDGxfGiuSUFKgVk7NYTktJGho6I8qdZUry/UQdmbLGp5";
    private static final String kPublic_Key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqa4doWOmRvGZdm/qxfBtaNDUFTbK0wCHkOo7sQvdmEt8TWLqRI91Z1heyeOHWIZk6FdfeRaOQVmJL1ZAkfkzGda+99B68Fk4fXjH2xvWO7K+V5D7aWfTJorXdLaRMmsoDa8fDCDc2oz4+NQ23oixH56w3y75yy44PyATFLXonSlfR0wYIOrc3jzLN54hvUxGfWFlgbrCoxlmFB5HAX1bFGChdOE8zSWef8ZrT3wG7m4CRSkYpxyZm/AafiH5HdQVarZQFcVOGVXP3StBfonHBUsajkIvm8j66IuqLXYhSwfRY/D+ydceJms72sjiUabuV+WCgs0LkuIuA0HucgJ1cwIDAQAB";

//    private static final String kPrivate_Key = "MIIEowIBAAKCAQEAl7sN3nz7f88fTGAiGLTaoOr1KMtkvoC0h9m0Ae7zuxLO3a489lPspSXY1/QSqRPYEkYtPnj5gOT9ZIF1y27lzJRDUJd7LhY/aGFmSg5rF2hcfrAohOy46VuAJI0Z0j+bYuSsNy821w/620msIK/r/uxYtJur+aQBqQqV2p7o7WkZDjX/0xTlwZFOm62nQ7+W0mgSQFgOLBJ5m3XuzA6U6pa21Auj11knaRX8t3oPdo+5tsNx4a2UXLJseOuwqeqMOebbzBk87Bn+2l819+K3CcNhhBBJT2x+sII2tuEA6zC7qnS9+Ge6BiXpVrPlk+09ywN6vv5GxL+T1kJ57WPoRwIDAQABAoIBAEL8RMo1uT6arUGlq0fnCCJEuIkTCl4EKi9TkGHOIXI0gnlhw+4n7PCX/dyRF2/nn9upea378ILUFX46nUt7oR4pUnKQ/cPB9KpbXbJSHTtPSo5vrOPKMnRrfe4lEQI+LJaDR/hw8rANkP0g0En6AKEhrKPHmivzGPyM/M1wnHq63lxvv5aH6FiEb9t+VfXuESPj/WlY6RB+pAHDZGxQwn3kzUsRi7WUt/xDQxa2gEnpsYWmllYdF+rGs6MrulcGuxnt3FVfLB+M4RGCAdjWsgrE52Xjt+j0PJg9EBX85MyrG9B+9H+/puB3Do43sUffFXzwdjWWInJkfbLt1wZXbkECgYEAxbgqR66KOnJeo8OLafQCgJ24gwtzI3cbmT5P7nTkOADdL/cTLc/ABNmlIc4KIgvSvUoumX2EGYclrm8OkCQpPrpTYmMow+ymu7WfbA2rTXH9hzhcacBfYyMJhXWx3bfbkvYuYfBx/BXAFEU1ecjcqGjWBbDx2OokE2vhq5XFnOECgYEAxHSY2Fse60JX+ebqxqp5k17Rpe8o+OL+kdxPC7Hx02QidDQtmrHdqHCjf4VTTdSLCPn40bs5CxEpjWJk16lAtFDArS/ABDcWLPC/pyJ57JV0hSlsoXda2bOOcB+0EDUqPeYS1mSiAe0f5bWEMcWO3kX6tmWq415ogDMQeaW3QicCgYA86I/1xxoECUmIT2v6NtYyguPdUsCkc0PIQH7lKZNIgVOiPA3ndfFkTRvmvw82D8ha0ahrVlREfPKpusKUut8N2N5pF7zuJk/y0W+MHOXhlLUSW9V0KnP4GUoMmAY0FDiLHFWLjEPA8X5bgDqKCsuXAby0wh6uwOpeJUS+1AOtYQKBgQCnYB+I1bl1/sQtqcuFD2Edab98fFKQGfWCGA1QjX7W941TK9Fe5wNOqwjhcJoUyWzbbP3M0pI7F5grWRVJmG4EMni2FOSnsrc1+reOkhUGuB7aBP0EZEgHCq/kX15uIJ2otwh9mKdetMRkVU4XiZW7UivUkrIRnTGzZ841ljaYKQKBgB0pfW4fVNKm+Gu3PlfDyAfpsmKFBxxwRBv13G8aWMKgBXxjMkMx5YotXhNi6rPhAEFUfh71DvirK98f/4ORIqjzcTGHZgSV95DBz2taQxOkuefDGeIgN1WxNImMZEGf13x2RgRUnAiWhhR4eCNJXq49oNqBqmCfFGkmtGWtbhDW";
//    private static final String kPrivate_Key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXuw3efPt/zx9MYCIYtNqg6vUoy2S+gLSH2bQB7vO7Es7drjz2U+ylJdjX9BKpE9gSRi0+ePmA5P1kgXXLbuXMlENQl3suFj9oYWZKDmsXaFx+sCiE7LjpW4AkjRnSP5ti5Kw3LzbXD/rbSawgr+v+7Fi0m6v5pAGpCpXanujtaRkONf/TFOXBkU6bradDv5bSaBJAWA4sEnmbde7MDpTqlrbUC6PXWSdpFfy3eg92j7m2w3HhrZRcsmx467Cp6ow55tvMGTzsGf7aXzX34rcJw2GEEElPbH6wgja24QDrMLuqdL34Z7oGJelWs+WT7T3LA3q+/kbEv5PWQnntY+hHAgMBAAECggEAQvxEyjW5PpqtQaWrR+cIIkS4iRMKXgQqL1OQYc4hcjSCeWHD7ifs8Jf93JEXb+ef26l5rfvwgtQVfjqdS3uhHilScpD9w8H0qltdslIdO09Kjm+s48oydGt97iURAj4sloNH+HDysA2Q/SDQSfoAoSGso8eaK/MY/Iz8zXCcerreXG+/lofoWIRv235V9e4RI+P9aVjpEH6kAcNkbFDCfeTNSxGLtZS3/ENDFraASemxhaaWVh0X6sazoyu6Vwa7Ge3cVV8sH4zhEYIB2NayCsTnZeO36PQ8mD0QFfzkzKsb0H70f7+m4HcOjjexR98VfPB2NZYicmR9su3XBlduQQKBgQDFuCpHroo6cl6jw4tp9AKAnbiDC3MjdxuZPk/udOQ4AN0v9xMtz8AE2aUhzgoiC9K9Si6ZfYQZhyWubw6QJCk+ulNiYyjD7Ka7tZ9sDatNcf2HOFxpwF9jIwmFdbHdt9uS9i5h8HH8FcAURTV5yNyoaNYFsPHY6iQTa+GrlcWc4QKBgQDEdJjYWx7rQlf55urGqnmTXtGl7yj44v6R3E8LsfHTZCJ0NC2asd2ocKN/hVNN1IsI+fjRuzkLESmNYmTXqUC0UMCtL8AENxYs8L+nInnslXSFKWyhd1rZs45wH7QQNSo95hLWZKIB7R/ltYQxxY7eRfq2ZarjXmiAMxB5pbdCJwKBgDzoj/XHGgQJSYhPa/o21jKC491SwKRzQ8hAfuUpk0iBU6I8Ded18WRNG+a/DzYPyFrRqGtWVER88qm6wpS63w3Y3mkXvO4mT/LRb4wc5eGUtRJb1XQqc/gZSgyYBjQUOIscVYuMQ8DxfluAOooKy5cBvLTCHq7A6l4lRL7UA61hAoGBAKdgH4jVuXX+xC2py4UPYR1pv3x8UpAZ9YIYDVCNftb3jVMr0V7nA06rCOFwmhTJbNts/czSkjsXmCtZFUmYbgQyeLYU5KeytzX6t46SFQa4HtoE/QRkSAcKr+RfXm4gnai3CH2Yp160xGRVTheJlbtSK9SSshGdMbNnzjWWNpgpAoGAHSl9bh9U0qb4a7c+V8PIB+myYoUHHHBEG/XcbxpYwqAFfGMyQzHlii1eE2Lqs+EAQVR+HvUO+Ksr3x//g5EiqPNxMYdmBJX3kMHPa1pDE6S558MZ4iA3VbE0iYxkQZ/XfHZGBFScCJaGFHh4I0lerj2g2oGqYJ8UaSa0Za1uENY=";
//    private static final String kPublic_Key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl7sN3nz7f88fTGAiGLTaoOr1KMtkvoC0h9m0Ae7zuxLO3a489lPspSXY1/QSqRPYEkYtPnj5gOT9ZIF1y27lzJRDUJd7LhY/aGFmSg5rF2hcfrAohOy46VuAJI0Z0j+bYuSsNy821w/620msIK/r/uxYtJur+aQBqQqV2p7o7WkZDjX/0xTlwZFOm62nQ7+W0mgSQFgOLBJ5m3XuzA6U6pa21Auj11knaRX8t3oPdo+5tsNx4a2UXLJseOuwqeqMOebbzBk87Bn+2l819+K3CcNhhBBJT2x+sII2tuEA6zC7qnS9+Ge6BiXpVrPlk+09ywN6vv5GxL+T1kJ57WPoRwIDAQAB";

    /**
     * 加密 默认使用上面配置的秘钥对
     * @param content 加密内容
     * @param type 使用公钥加密还是私钥加密
     * @return 加密结果
     */
    public static String encrypt(String content, RSAKeyType type) {
        String keyStr = type == RSAKeyType.PUBLIC ? kPrivate_Key : kPublic_Key;
        return encrypt(content, type, keyStr);
    }

    /**
     * 加密
     * @param content 加密内容
     * @param type 使用公钥加密还是私钥加密
     * @param keyStr 加密对应type的公钥或者私钥
     * @return 解密内容
     */
    public static String encrypt(String content, RSAKeyType type, String keyStr) {
        try {
            Key key = RSAEncrypt.loadRSAKeyByStr(keyStr,type);
//            return Base64.encode(encrypt(key,content.getBytes()));
            return Base64.encode(docrypt(key,content, Cipher.ENCRYPT_MODE));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    public static String decrypt(String content, RSAKeyType type) {
        String keyStr = type == RSAKeyType.PRIVATE ? kPrivate_Key : kPublic_Key;
        return decrypt(content,type, keyStr);
    }

    /**
     * 解密
     * @param content
     * @param type
     * @param keyStr
     * @return
     */
    public static String decrypt(String content, RSAKeyType type, String keyStr) {
        try {
            Key key = RSAEncrypt.loadRSAKeyByStr(keyStr,type);
//            byte [] res = decrypt(key, Base64.decode(content));
            byte [] res = docrypt(key,content,Cipher.DECRYPT_MODE);
            return new String(res);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 加密解密,根据mode key
     * @param rsaKey 公钥私钥
     * @param content 加解密内容
     * @param mode  Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE
     * @return byte[]
     * @throws Exception
     */
    private static byte[] docrypt(Key rsaKey, String content, int mode)
            throws Exception {
        byte [] data;
        String s;
        if (mode == Cipher.ENCRYPT_MODE) { // 加密
            data = content.getBytes();
            s = "明文";
        } else { //解密
            data = Base64.decode(content);
            s = "密文";
        }
        try {
            // 使用默认RSA
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(mode, rsaKey);
            byte[] output = cipher.doFinal(data);
            return output;
        } catch (NoSuchAlgorithmException e) {
            String info = mode==Cipher.ENCRYPT_MODE?"加密":"解密";
            throw new Exception("无此"+info+"算法");
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidKeyException e) {
            throw new Exception("秘钥非法,请检查");
        } catch (IllegalBlockSizeException e) {
            throw new Exception(s+"长度非法");
        } catch (BadPaddingException e) {
            throw new Exception(s+"数据已损坏");
        }
    }


    /**
     * 秘钥串 转 RSAKey
     * @param str 秘钥字符串
     * @param type RSAKeyType 公钥私钥类型
     * @return RSAKey
     * @throws Exception
     */
    private static Key loadRSAKeyByStr(String str, RSAKeyType type) throws Exception
    {

        String typeStr = "";
        try {
            byte[] buffer = Base64.decode(str);
            if (type == RSAKeyType.PRIVATE) {
                typeStr = "私钥";
                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
                return KeyFactory.getInstance("RSA").generatePrivate(keySpec);
            } else {
                typeStr = "公钥";
                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
                return KeyFactory.getInstance("RSA").generatePublic(keySpec);
            }
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception(typeStr+"非法");
        } catch (NullPointerException e) {
            throw new Exception(typeStr+"数据为空");
        }
    }


    /**
     * 随机生成密钥对
     */
    public static void genKeyPair(String filePath) {
        // KeyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 初始化密钥对生成器，密钥大小为96-2048位
        keyPairGen.initialize(2048,new SecureRandom());
        // 生成一个密钥对，保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        try {
            // 得到公钥字符串
            String publicKeyString = Base64.encode(publicKey.getEncoded());
            // 得到私钥字符串
            String privateKeyString = Base64.encode(privateKey.getEncoded());
            // 将密钥对写入到文件
            FileWriter pubfw = new FileWriter(filePath + kPublic_Key_File);
            FileWriter prifw = new FileWriter(filePath + kPrivate_Key_File);
            BufferedWriter pubbw = new BufferedWriter(pubfw);
            BufferedWriter pribw = new BufferedWriter(prifw);
            pubbw.write(publicKeyString);
            pribw.write(privateKeyString);
            pubbw.flush();
            pubbw.close();
            pubfw.close();
            pribw.flush();
            pribw.close();
            prifw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从文件中加载文件数据 to String
     *
     * @param path  /data/private_key.keystore
     * @return 是否成功
     * @throws Exception
     */
    public static String loadKeyByFilePath(String path) throws Exception {
        try {
            BufferedReader br = new BufferedReader(new FileReader(path));
            String readLine;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                if (readLine.charAt(0) != '-') sb.append(readLine);
            }
            br.close();
            String s = sb.toString();
            return s;
        } catch (IOException e) {
            throw new Exception("文件数据读取错误");
        } catch (NullPointerException e) {
            throw new Exception("文件输入流为空");
        }
    }



    /**
     * 字节数据转字符串专用集合
     */
    private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    /**
     * 字节数据转十六进制字符串
     *
     * @param data
     *            输入数据
     * @return 十六进制内容
     */
    public static String byteArrayToString(byte[] data) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < data.length; i++) {
            // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
            stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
            // 取出字节的低四位 作为索引得到相应的十六进制标识符
            stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
            if (i < data.length - 1) {
                stringBuilder.append(' ');
            }
        }
        return stringBuilder.toString();
    }
}
